package com.ruoyi.web.controller.utils;

import com.ruoyi.common.utils.sign.Md5Utils;
import com.ruoyi.mall.domain.MallMemberUser;

import com.ruoyi.web.AppBeanInjector;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.client.RestTemplate;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;



/**
 * 功能：
 *
 * @author：LCL
 * @create：2022-03-03
 */
public abstract class WeixinUtils {
	private static final Logger logger = LoggerFactory.getLogger(WeixinUtils.class);
	private static final String TRADE_TYPE = "xcx";
	public static final String CHARSET = "utf-8";
	private static String Key = "2e15db0ce34d4a2abfe7adfb43346d9a";
	/**
	 * appid:公众号的唯一标识
	 *
	 *redirect_uri:重定向的url,就是授权后要跳转的页面
	 *
	 *scope:应用授权作用域
	 *
	 *		snsapi_base:不弹出授权页面，直接跳转，只能获取用户openid
	 *
	 *		snsapi_userinfo:弹出授权页面，可通过openid拿到昵称、性别、所在地
	 *
	 *state:重定向后带的参数
	 */
	private static String c_web_authorization_path = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope=snsapi_userinfo&state={2}#wechat_redirect";
	public static final String c_auth_scope_login = "snsapi_login";


	public static HttpURLConnection createConnection(String url, String method) throws Exception {
		return createConnection(url, method, "application/x-www-form-urlencoded",null);
	}

	public static HttpURLConnection createConnection(String url, String method, String contentType,String outputStr) throws Exception {
		URL requstUrl = new URL(url);
		HttpURLConnection http = (HttpURLConnection) requstUrl.openConnection();
		http.setRequestMethod(method);
		http.setRequestProperty("Content-Type", contentType);// 当outputStr不为null时向输出流写数据
		http.setDoOutput(true);
		http.setDoInput(true);
		if (null != outputStr) {
			OutputStream outputStream = http.getOutputStream();
			// 注意编码格式
			outputStream.write(outputStr.getBytes("UTF-8"));
			outputStream.close();
		}
		System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
		System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
		return http;
	}

	private static String _parseFromHttpURLConncection(HttpURLConnection httpConnection) throws Exception {
		Assert.notNull(httpConnection,"httpConnection不能为空");
		InputStream is = httpConnection.getInputStream();
		int size = is.available();
		byte[] jsonBytes = new byte[size];
		is.read(jsonBytes);
		String message = new String(jsonBytes, "UTF-8");
		is.close();
		return message;
	}

	public static JSONObject parseFromHttpURLConncection(HttpURLConnection httpConnection) throws Exception {
		String message = _parseFromHttpURLConncection(httpConnection);
		return new JSONObject(message);
	}

	public static String getQrCodeImg(MallMemberUser member) {
		String url = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token={0}";
		url = FBSStringUtil.format(url,getXCXToken().get("access_token"));
		RestTemplate rest = new RestTemplate();

		HashMap<String, Object> map = new HashMap<>();
		map.put("path","pages/index/index?referrerID="+member.getId());
//		map.put("path","pages/index/index?referrerID="+member.getId()+"isCompany"+member.getIsCompany());
		map.put("width",430);
		MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
		HttpEntity requestEntity = new HttpEntity<>(map, headers);
		ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
		// System.out.println("调用小程序生成微信永久小程序码URL接口返回结果:" + entity.getBody());
		byte[] result = entity.getBody();
		String fileName = member.getId() + ".jpg";
		AppBeanInjector.qiniuUploadUtil.upload(result,fileName);
		return QiNiuUploadUtil.getBaseUrl()+fileName;
//		String file = "/qrCode/"+member.getId() + ".jpg";
//		String fileName = RuoYiConfig.getUploadPath()+ file;
//		FileUploadUtils.getFileByBytes(result,fileName);
//		file = "https://server.szyujingkeji.com"+ Constants.RESOURCE_PREFIX+"/upload"+file;
//		return file;
	}

	public static JSONObject getXCXToken() {
		String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
		url = FBSStringUtil.format(url,"wxb2bacd262ba9746b","6fa7d6e11b40ca96184d074d8d4b88dd");
		try {
			HttpURLConnection connection = createConnection(url, RequestMethod.GET.toString());
			connection.connect();
			JSONObject jsonObject = parseFromHttpURLConncection(connection);
			connection.disconnect();
			return jsonObject;
		} catch (Exception e) {
			logger.error("获取用户信息出现异常",e);
		}
		return null;
	}

	public static String getPerpayId(SortedMap<String,Object> data,SortedMap<String,Object> data2) {
		String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		try {
			HttpURLConnection connection = createConnection(url,RequestMethod.POST.toString(),"application/x-www-form-urlencoded",getXml(data));

			// 从输入流读取返回内容
			InputStream inputStream = connection.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
			String str = null;
			StringBuffer buffer = new StringBuffer();
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			// 释放资源
			bufferedReader.close();
			inputStreamReader.close();
			inputStream.close();
			inputStream = null;
			connection.disconnect();
			System.out.println(buffer.toString());
			Map<String,String> resultMap = null;
			resultMap = doXMLParse(buffer.toString());
			if(resultMap!=null){
				String nonce_str = resultMap.get("nonce_str");
				String prepay_id = resultMap.get("prepay_id");
				data2.put("nonceStr",nonce_str);
				return prepay_id;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	//xml解析
	public static Map doXMLParse(String strxml) throws JDOMException, IOException {

		if(null == strxml || "".equals(strxml)) {
			return null;
		}

		Map m = new HashMap();

		InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
		SAXBuilder builder = new SAXBuilder();
		Document doc = builder.build(in);
		Element root = doc.getRootElement();
		List list = root.getChildren();
		Iterator it = list.iterator();
		while(it.hasNext()) {
			Element e = (Element) it.next();
			String k = e.getName();
			String v = "";
			List children = e.getChildren();
			if(children.isEmpty()) {
				v = e.getTextNormalize();
			} else {
				v = getChildrenText(children);
			}

			m.put(k, v);
		}

		//关闭流
		in.close();

		return m;
	}

	public static String getChildrenText(List children) {
		StringBuffer sb = new StringBuffer();
		if(!children.isEmpty()) {
			Iterator it = children.iterator();
			while(it.hasNext()) {
				Element e = (Element) it.next();
				String name = e.getName();
				String value = e.getTextNormalize();
				List list = e.getChildren();
				sb.append("<" + name + ">");
				if(!list.isEmpty()) {
					sb.append(getChildrenText(list));
				}
				sb.append(value);
				sb.append("</" + name + ">");
			}
		}

		return sb.toString();
	}

	/**
	 * 微信支付签名算法sign
	 * @param characterEncoding
	 * @param parameters
	 * @return
	 */
	public static String createSign(String characterEncoding,SortedMap<String,Object> parameters){
		StringBuffer sb = new StringBuffer();
		Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序（升序）
		Iterator it = es.iterator();
		while(it.hasNext()) {
			Map.Entry entry = (Map.Entry)it.next();
			String k = (String)entry.getKey();
			Object v = entry.getValue();
			if(null != v && !"".equals(v)
					&& !"sign".equals(k) && !"key".equals(k)) {
				sb.append(k + "=" + v + "&");
			}
		}
		sb.append("key=" + Key);
		System.out.println("xxxxxxx:"+sb);
		String sign = Md5Utils.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
		return sign;
	}

	private static String getXml(SortedMap<String,Object> data) {
		String xml ="<xml>\n" +
				"   <appid>"+data.get("appid")+"</appid>\n" +
				"   <attach>"+data.get("attach")+"</attach>" +
				"   <openid>"+data.get("openid")+"</openid>" +
				"   <body>"+data.get("body")+"</body>" +
				"   <mch_id>"+data.get("mch_id")+"</mch_id>" +
				"   <nonce_str>"+data.get("nonce_str")+"</nonce_str>" +
				"   <notify_url>"+data.get("notify_url")+"</notify_url>" +
				"   <out_trade_no>"+data.get("out_trade_no")+"</out_trade_no>" +
				"   <spbill_create_ip>"+data.get("spbill_create_ip")+"</spbill_create_ip>" +
//				"   <time_start>"+DateUtils.getDate()+"</time_start>" +
				"   <total_fee>"+data.get("total_fee")+"</total_fee>" +
				"   <trade_type>"+data.get("trade_type")+"</trade_type>" +
				"   <sign>"+createSign(CHARSET,data)+"</sign>" +
				"</xml>";
		return xml;
	}

}
